﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using ProgNetComponents.Data.SqlCe;
using System.Data;
using ProgNetComponentsDx.Browsers;
using System.Text.RegularExpressions;
using ProgNetComponentsDx.Options;
using WindowsInput;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using ProgNetComponents.Classes;
using BuildHelper.Scheduler;

namespace BuildHelper.Setup.BazyDanych
{
    public static class Tools
    {
        static RegexOptions op = RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline;
        
        public static string GetConnectionString(string host, string port, string service, string sid, string user, string pass)
        {
            return "Data Source=(DESCRIPTION=(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = " + host +
                        ")(PORT = " + port + ")))(CONNECT_DATA = (SERVER=DEDICATED)(" +
                        (service.IsNotNull() ? ("SERVICE_NAME = " + service) :
                        ("SID = " + sid)) +
                        ")));User Id=" + user + ";Password=" + pass + ";";
        }
        private static List<string> _InvalidHosts = new List<string>();
        private static void GetFromWeb(string envName, string dbcheck, DbData d, ExtendedWebClient wc, out string ShortName, out string telnetUser)
        {
            string host = "";
            string port = "";
            string sid = "";
            string service = "";
            string text = "";
            string dbString = "";
            ShortName = "";
            telnetUser = "";
            try
            {
                text = wc.DownloadString(dbcheck);
                string user = text.GetFirstMatch("<p>\\s*User:\\s(.*?)\\s*</p>", 1, op);
                dbString = text.GetFirstMatch("<p>\\s*Database url:\\s*jdbc:oracle:thin:[/@]*(.*?)\\s*</p>", 1, op);
                string serviceMask = "(.*?):(\\d*)/([^\\s]*)"; //host:port/service
                string sidMask = "(.*?):(\\d*):([^\\s]*)"; //host:port:sid  
                ShortName = text.GetFirstMatch("<p>\\s*Database url:\\s*jdbc:oracle:thin:[/@]*(\\w*)\\s*</p>");
                string webUser = text.GetFirstMatch("Environment:\\s*<b>(.*?)</b>", 1, op);
                List<string> list = webUser.GetMatches("([a-zA-Z0-9]+)");
                if (list.Count > 0)
                {
                    telnetUser = list[list.Count - 1].GetFirstMatch("(D?[0-9]*)");
                }
                if (dbString.IsNotNull())
                {
                    if (dbString.XMatch(serviceMask, op))
                    {
                        host = dbString.GetFirstMatch(serviceMask, 1, op);
                        port = dbString.GetFirstMatch(serviceMask, 2, op);
                        service = dbString.GetFirstMatch(serviceMask, 3, op);
                    }
                    else if (dbString.XMatch(sidMask, op))
                    {
                        host = dbString.GetFirstMatch(serviceMask, 1, op);
                        port = dbString.GetFirstMatch(serviceMask, 2, op);
                        sid = dbString.GetFirstMatch(serviceMask, 3, op);
                    }
                    else
                    {
                        host = dbString.GetFirstMatch(@"\(HOST\s*=\s*(.*?)\s*\)", 1, op);
                        port = dbString.GetFirstMatch(@"\(PORT\s*=\s*(.*?)\s*\)", 1, op);
                        service = dbString.GetFirstMatch(@"\(SERVICE_NAME\s*=\s*(.*?)\s*\)", 1, op);
                        sid = dbString.GetFirstMatch(@"\(SID\s*=\s*(.*?)\s*\)", 1, op);
                    }
                    d.UserName = user;
                    d.Pass = user;
                    d.Host = host;
                    d.Port = port.AsInt();
                    d.Service = service;
                    d.Sid = sid;
                }
            }
            catch (System.Net.WebException)
            {
                //ignore
            }
            catch (Exception ex)
            {
                ex.LogInternal("ERROR IN GetFromWeb: envName: " + envName + "; dbcheck: " + dbcheck);
            }
        }
        private static void GetFromTelnet(string envName, string telnetUser, string ShortName, DbData d)
        {
            try
            {
                string envUrl = "";
                string envHost = "";
                string envWersja = "";
                DataTable dt = BrowserCache.GetBrowserData(Init.InitFormBrowserNames.Setup.Srodowiska);
                if (dt != null)
                {
                    DataRow r = dt.SelectFirstRow("STP_SR_NAZWA = " + envName.EscapeSql());
                    if (r != null)
                    {
                        envUrl = r["STP_SR_URL"].AsString();
                        envHost = r["STP_SR_HOST"].AsString();
                        envWersja = r["STP_SR_WERSJA"].AsString();
                    }
                }
                string telnetHost = envHost;
                if (telnetUser.IsNullOrEmpty())
                {
                    List<string> list = envName.GetMatches("([a-zA-Z0-9]+)");
                    if (list.Count > 0)
                    {
                        telnetUser = list[list.Count - 1].GetFirstMatch("(D?[0-9]+)");
                    }
                }

                if (telnetUser.IsNotNull() && telnetHost.IsNotNull())
                {
                    if (!_InvalidHosts.Contains(telnetHost))
                    {
                        if (!TryGetDbDataFromTelnet(d, telnetHost, telnetUser, ShortName))
                        {
                            if (!telnetUser.Contains("d") && envName.ToLower().Contains("d"))
                            {
                                telnetUser = "d" + telnetUser;
                                TryGetDbDataFromTelnet(d, telnetHost, telnetUser, ShortName);
                            }
                        }
                    }
                }
            }
            catch (System.Net.WebException)
            {
                //ignore
            }
            catch (Exception ex)
            {
                ex.LogInternal("ERROR IN GetFromTelnet envName: " + envName + ", telnetUser: " + telnetUser + ", ShortName:" + ShortName);
            }
        }
        private static bool TryGetDbData(string envName, string dbcheck, DbData d, ExtendedWebClient wc, bool getFromWeb, string telnetUser)
        {
            bool result = false;
            string ShortName = "";
            string telnetUserWeb = "";
            #region read from web page
            if (getFromWeb)
                GetFromWeb(envName, dbcheck, d, wc, out ShortName, out telnetUserWeb);

            #endregion

            #region read from telnet
            
            if (d.Host.IsNull())
            {
                if (telnetUser.IsNotNull())
                {
                    GetFromTelnet(envName, telnetUser, ShortName, d);
                }
                if (d.Host.IsNull())
                {
                    if (telnetUser != telnetUserWeb)
                    {
                        GetFromTelnet(envName, telnetUserWeb, ShortName, d);
                    }
                }
            }
            
            #endregion
            
            result = d.Host.IsNotNull() && d.UserName.IsNotNull();

            return result;
        }
        public static void ClearInvalidHosts()
        {
            _InvalidHosts.Clear();
        }
        private static bool GetFromTnsping(TelnetConnection c, string shortName, DbData d)
        {
            if (shortName.IsNotNull())
            {
                //c.ReadToEnd();
                c.WriteLine("tnsping " + shortName);
                System.Threading.Thread.Sleep(100);
                string s = c.ReadToEnd();
                RegexOptions op = RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline;

                string host = s.GetFirstMatch(@"\(HOST\s*=\s*(.*?)\s*\)", 1, op);
                string port = s.GetFirstMatch(@"\(PORT\s*=\s*(.*?)\s*\)", 1, op);
                string service = s.GetFirstMatch(@"\(SERVICE_NAME\s*=\s*(.*?)\s*\)", 1, op);
                string sid = s.GetFirstMatch(@"\(SID\s*=\s*(.*?)\s*\)", 1, op);
                if (host.IsNotNull())
                {
                    d.Host = host;
                    d.Port = port.AsInt();
                    d.Service = service;
                    d.Sid = sid;
                    return true;
                }
            }
            return false;
        }
        private static bool TryParse(TelnetConnection c, string conString, DbData d)
        {
            string serviceMask = "(.+)/(.+)[/@](.*?):(\\d*)/([^\\s]*)"; //host:port/service
            string sidMask = "(.+)/(.+)[/@](.*?):(\\d*):([^\\s]*)"; //host:port:sid  
            string shortMask = "(.+)/(.+)@(.*)";
           
            if (conString.XMatch(serviceMask))
            {
                d.Host = conString.GetFirstMatch(serviceMask, 3).Trim();
                d.Port = conString.GetFirstMatch(serviceMask, 4).Trim().AsInt(-1);
                d.Service = conString.GetFirstMatch(serviceMask, 5).Trim();

                d.UserName = conString.GetFirstMatch(serviceMask, 1).Trim();
                d.Pass = conString.GetFirstMatch(serviceMask, 2).Trim();
            }
            else if (conString.XMatch(sidMask))
            {
                d.Host = conString.GetFirstMatch(sidMask, 3).Trim();
                d.Port = conString.GetFirstMatch(sidMask, 4).Trim().AsInt(-1);
                d.Sid = conString.GetFirstMatch(sidMask, 5).Trim();

                d.UserName = conString.GetFirstMatch(sidMask, 1).Trim();
                d.Pass = conString.GetFirstMatch(sidMask, 2).Trim();
            }
            else if (conString.XMatch(shortMask))
            {
                string shortName = conString.GetFirstMatch(shortMask, 3).Trim();
                if (GetFromTnsping(c, shortName, d))
                {
                    d.UserName = conString.GetFirstMatch(shortMask, 1).Trim();
                    d.Pass = conString.GetFirstMatch(shortMask, 2).Trim();
                }
            }
            else
            {
                string shortName = conString.Trim();
                if (shortName.StartsWith("/"))
                    shortName = shortName.Trim().Replace("/", "");
                if (shortName.StartsWith("@"))
                    shortName = shortName.Trim().Replace("@", "");
                if (shortName.XMatch("^\\w*$"))
                    GetFromTnsping(c, shortName, d);
            }
            if (d.UserName.XMatch("TNS PING"))
            {
                c.ReadToEnd();
                c.WriteLine("cat $GGCMPARAM");
                string conStringT = c.ReadToEnd();
                conStringT += c.ReadToEnd();

                d.UserName  = conStringT.GetFirstMatch("DB_USER_NAME\\s*\"([^\"]*)\"");
                d.Pass = conStringT.GetFirstMatch("DB_PASSWORD\\s*\"([^\"]*)\"");
            }

            return d.Host.IsNotNull();
        }
        private static bool TryGetDbDataFromTelnet(DbData d, string telnetHost, string telnetUser, string shortName)
        {
            bool result = false;
            TelnetConnection c = null;
            string telnetUserNum = telnetUser.XReplace("[^0-9]*", "");
            try
            {
                RegexOptions op = RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline;

                try
                {
                    c = new TelnetConnection(telnetHost, 23);
                }
                catch (Exception ex)
                {
                    _InvalidHosts.Add(telnetHost);
                    ex.LogInternal("ERROR in TryGetDbDataFromTelnet: Błąd połączenia z " + telnetHost);
                }
                if (c != null)
                {
                    if (telnetUser.XMatch("d", op))
                        telnetUserNum += "d";
                    telnetUserNum = telnetUserNum + "scc";
                    c.Login(telnetUserNum, 100);
                    string line = c.ReadToEnd();
                    c.WriteLine("");
                    line = c.ReadToEnd();
                  
                    if (shortName.IsNotNull())
                        GetFromTnsping(c, shortName, d);
                    if (d.Host.IsNull())
                    {
                        c.ReadToEnd();
                        c.WriteLine("cat $GGCMPARAM");
                        string conString = c.ReadToEnd();
                        
                        string user = conString.GetFirstMatch("DB_USER_NAME\\s*\"([^\"]*)\"");
                        string pass = conString.GetFirstMatch("DB_PASSWORD\\s*\"([^\"]*)\"");
                        conString = conString.GetFirstMatch("DB_STRING\\s*\"([^\"]*)\"");

                        if (TryParse(c, conString, d))
                        {
                            if (user.IsNotNull())
                                d.UserName = user;
                            if (pass.IsNotNull())
                                d.Pass = pass;
                        }
                    }
                    if (d.Host.IsNull())
                    {
                        c.ReadToEnd();
                        c.WriteLine("echo $DORA_DB");
                        string conString = c.ReadToEnd();
                        string[] lines = conString.Split('\n');
                        if (lines.Length > 1 && lines[0].XMatch("echo"))
                            conString = lines[1];
                        TryParse(c, conString, d);
                    }
                    result = d.Host.IsNotNull() && d.UserName.IsNotNull();
                }
            }
            catch (Exception ex)
            {
                if (ex.Message.XMatch("no login prompt"))
                {
                    ("ERROR IN TryGetDbDataFromTelnet(telnetHost:" + telnetHost + ", telnetUserNum: " + telnetUserNum + ", shortName:" + shortName).LogInternal();
                }
                else
                {
                    ex.LogInternal("ERROR IN TryGetDbDataFromTelnet(telnetHost:" + telnetHost + ", telnetUserNum: " + telnetUserNum + ", shortName:" + shortName);
                }
            }
            finally
            {
                if (c != null)
                {
                    c.Dispose();
                }
            }
            return result;
        }
        public static DbData GetDbData(string envName, bool refreshEnv = false)
        {
            DbData d = new DbData();
            try
            {
                d.EnvName = envName;
                string envUrl = "";
                string envHost = "";
                string envWersja = "";
                string telnetUser = "";
                bool dziala = true;
                if (refreshEnv)
                {
                    BuildHelper.Setup.Srodowiska.Tools.EnvData env = Srodowiska.Tools.GetEnvData(null, envName);
                    if (env != null && env.Processed)
                    {
                        envUrl = env.Url;
                        envHost = env.Host;
                        env.Wersja = env.Wersja;
                    }
                }
                else
                {
                    DataTable dt = BrowserCache.GetBrowserData(Init.InitFormBrowserNames.Setup.Srodowiska);
                    if (dt != null)
                    {
                        DataRow r = dt.SelectFirstRow("STP_SR_NAZWA = " + envName.EscapeSql());
                        if (r != null)
                        {
                            envUrl = r["STP_SR_URL"].AsString();
                            envHost = r["STP_SR_HOST"].AsString();
                            envWersja = r["STP_SR_WERSJA"].AsString();
                            dziala = r["STP_SR_DZIALA"].AsBool();
                            telnetUser = r["STP_SR_USER"].ToString();
                        }
                    }
                }
                if (envUrl.IsNotNullOrEmpty())
                {
                    bool skipWebNotResponding = OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.GetOnlyFromTelnet);
                    bool getFromWeb = true;
                    if (skipWebNotResponding)
                        getFromWeb = dziala;
                    
                    string dbcheck = envUrl + "/dbcheck.jsp";
                    ExtendedWebClient wc = GlobalTools.GetWebClient();
                    wc.Timeout = OptionCache.GetOptionValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.TimeOut).AsInt(10000);
                    if (!TryGetDbData(envName, dbcheck, d, wc, getFromWeb, telnetUser))
                    {
                        if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.DoubleCheck))
                        {
                            wc.Timeout *= 2;
                            TryGetDbData(envName, dbcheck, d, wc, getFromWeb, telnetUser);
                        }
                    }
                    
                    if (d.Host.IsNotNullOrEmpty() && d.UserName.IsNotNull())
                    {
                        d.Wersja = envWersja;
                        System.Data.OracleClient.OracleConnection c = new System.Data.OracleClient.OracleConnection();
                        c.ConnectionString = GetConnectionString(d.Host, d.Port.AsString(), d.Service, d.Sid, d.UserName, d.Pass);
                        System.Data.OracleClient.OracleCommand cmd = c.CreateCommand();
                        try
                        {
                            object obj = null;
                            string query = "SELECT GA_GCM_RELEASE FROM GA_GCM_DBVERS WHERE GA_GCM_VER = (SELECT MAX(GA_GCM_VER) FROM GA_GCM_DBVERS)";
                            cmd.CommandText = query;
                            c.Open();
                            obj = cmd.ExecuteOracleScalar();
                            if (obj.IsNotNull() && obj.AsString().XMatch("\\d+\\.\\d+\\."))
                                d.Wersja = obj.AsString();
                        }
                        catch { }
                        finally
                        {
                            c.Close();
                            cmd.Dispose();
                            c.Dispose();
                        }
                    }
                    else
                    {
                        d = null;
                    }
                }
                else
                {
                    d = null;
                }
            }
            catch (Exception ex)
            {
                d = null;
                ex.LogInternal(" ERROR IN GetDbData; envName: " + envName);
            }
            return d;
        }
        private static void UpdateDb(params DbData[] dbs)
        {
            try
            {
                if (dbs != null)
                {
                    SqlCeDataManager m = new SqlCeDataManager();
                    m.AutoLogExceptions = true;
                    m.AutoCommit = true;
                    BazyDanychDataSet s = new BazyDanychDataSet();
                    m.AddTableDef(s.STP_BAZY_DANYCH, "SELECT * FROM STP_BAZY_DANYCH WHERE STP_BD_NAZWA = @NAZWA");
                    foreach (DbData e in dbs)
                    {
                        if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.AutoAddTnsNames))
                        {
                            GlobalTools.DBTools.AddTnsNames(e.EnvName, e.Host, e.Port.AsString(), e.Service, e.Sid);
                        }
                        if (BazyDanych.FormBazyDanych.Instance != null)
                        {
                            if (e.Host.IsNotNull())
                            {
                                try { BazyDanych.FormBazyDanych.Instance.MergeRow(e); }
                                catch { }
                            }
                        }
                        else
                        {
                            s.Clear();
                            m.FillDataSet(s, new NamedObject("@NAZWA", e.EnvName));

                            DataRow r = s.STP_BAZY_DANYCH.SelectFirstRow();
                            bool modified = true;

                            if (r == null)
                            {
                                r = s.STP_BAZY_DANYCH.NewRow();
                                r["STP_BD_NAZWA"] = e.EnvName;
                                s.STP_BAZY_DANYCH.Rows.Add(r);
                                modified = false;
                            }

                            modified |= r.SetColVal("STP_BD_", e.Host);
                            modified |= r.SetColVal("STP_BD_HOST", e.Host);
                            if (e.Port.IsNotNull())
                                modified |= r.SetColVal("STP_BD_PORT", e.Port);
                            else
                                modified |= r.SetColVal("STP_BD_PORT", DBNull.Value);
                            modified |= r.SetColVal("STP_BD_WLASNA", false);
                            modified |= r.SetColVal("STP_BD_SERVICE", e.Service);
                            modified |= r.SetColVal("STP_BD_SID", e.Sid);
                            modified |= r.SetColVal("STP_BD_USER", e.UserName);
                            modified |= r.SetColVal("STP_BD_PASS", e.Pass);
                            modified |= r.SetColVal("STP_BD_WERSJA", e.Wersja);
                            modified |= r.SetColVal("STP_BD_DATA_AKTUALIZACJI", DateTime.Now);
                        }
                        m.UpdateDataSet(s);
                    }
                    m.Dispose();
                }
            }
            catch (Exception ex)
            {
                ex.LogError();
            }
        }
        #region Update Db
        private class UpdateDbInfo
        {
            public UpdateDbInfo(string[] n, UpdateAllDbInfo a = null)
            {
                EnvNames = n;
                AllInfo = a;
            }
            public string[] EnvNames
            {
                get;
                set;
            }
            public UpdateAllDbInfo AllInfo
            {
                get;
                set;
            }
        }
        public static void UpdateDb(string envName)
        {
            Thread t = new Thread(new ParameterizedThreadStart(UpdateDbTh));
            t.Start(new UpdateDbInfo(new string[] { envName }));
        }
        public static void UpdateDb(string[] envs)
        {
            Thread t = new Thread(new ParameterizedThreadStart(UpdateDbTh));
            t.Start(new UpdateDbInfo(envs));
        }
        public static string GetUpdateDbId(string env)
        {
            return "UPD_DB " + env;
        }
        private static void UpdateDbTh(object arg)
        {
            UpdateDbInfo a = arg as UpdateDbInfo;
            if (a != null)
            {
                try
                {
                    DbData e;
                    string envName;
                    List<DbData> dbs = new List<DbData>();
                    List<string> del = new List<string>();
                    for (int i = 0; i < a.EnvNames.Length; i++)
                    {
                        if (a.AllInfo != null)
                        {
                            a.AllInfo.ProcessedDb++;
                            a.AllInfo.UpdateForm();
                        }
                        envName = a.EnvNames[i];
                       
                        e = GetDbData(envName, false);
                        if (e != null && e.Host.IsNotNull())
                            dbs.Add(e);
                        else
                            del.Add(envName);
                    }
                    UpdateDb(dbs.ToArray());
                    if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.KasujNieistniejace))
                    {
                        using (SqlCeDataManager m = new SqlCeDataManager())
                        {
                            m.AutoLogExceptions = true;
                            m.AutoCommit = true;
                            BazyDanychDataSet s = new BazyDanychDataSet();
                            m.AddTableDef(s.STP_BAZY_DANYCH, "SELECT * FROM STP_BAZY_DANYCH WHERE STP_BD_NAZWA = @NAZWA");
                            NamedObject obj = new NamedObject("@NAZWA", "");
                            foreach (string env in del)
                            {
                                if (BazyDanych.FormBazyDanych.Instance != null)
                                {
                                    try { BazyDanych.FormBazyDanych.Instance.DeleteEnv(env); }
                                    catch { }
                                }
                                else
                                {
                                    obj.Value = env;
                                    m.ExecuteNonQuery("DELETE FROM STP_BAZY_DANYCH WHERE STP_BD_NAZWA = @NAZWA", obj);
                                }
                            }
                        }
                    }
                }
                finally
                {
                    try
                    {
                        if (a.AllInfo != null)
                            a.AllInfo.ThreadsCount--;
                        else if (a.EnvNames.Length == 1)
                        {
                            BrowserCache.RefreshCacheForTable("STP_BAZY_DANYCH");
                            FormMain.CloseAlertById(GetUpdateDbId(a.EnvNames[0]));
                        }
                    }
                    catch { }
                }
            }
        }

       
        #endregion

        #region Update all Db
        static int updDbId = 0;
        private class UpdateAllDbInfo
        {
            public UpdateAllDbInfo(int n, DataRow row)
            {
                Index = n;
                Row = row;
            }
            public DataRow Row
            {
                get;
                private set;
            }
            public int Index
            {
                get;
                set;
            }
            public int ThreadsCount
            {
                get;
                set;
            }
            public int MaxEnvs
            {
                get;
                set;
            }
            public int ProcessedDb
            {
                get;
                set;
            }
            public void UpdateForm()
            {
                FormMain.UpdateAlertText(GetUpdateAllDbId(Index), "Uaktualnianie baz danych\n" + ProcessedDb.ToString() + "/" + MaxEnvs);
            }
        }
        public static void UpdateAllDb(bool showInfo, DataRow row)
        {
            if (showInfo)
            {
                string msg = "Uaktualnianie baz danych";
                System.Drawing.Image img = FormMain.Instance.MenuControl.commonImageCollectionFull1.Images[96];
                FormMain.AlertInfo a = new FormMain.AlertInfo(true, GetUpdateAllDbId(updDbId));
                FormMain.ShowAlert(msg, img, a);
            }
            Thread t = new Thread(new ParameterizedThreadStart(UpdateAllDbTh));
            t.Start(new UpdateAllDbInfo(updDbId, row));
            updDbId++;
        }
        
        private static string GetUpdateAllDbId(int i)
        {
            return "UPDATE_DB_" + i;
        }
        private static void UpdateAllDbTh(object arg)
        {
            UpdateAllDbInfo a = arg as UpdateAllDbInfo;
            if (a != null)
            {
                DataTable dt = BrowserCache.GetBrowserData(Init.InitFormBrowserNames.Setup.Srodowiska).Copy();
                List<DataRow> envsRows = new List<DataRow>();
                bool updateOnlyActive = OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.UaktualniajTylkoDzialajace);

                foreach (DataRow r in dt.Rows)
                {
                    if (!updateOnlyActive || r["STP_SR_DZIALA"].AsBool())
                    {
                        envsRows.Add(r);
                    }
                }
                int max = envsRows.Count;
                a.MaxEnvs = max;
                a.UpdateForm();
                int minCount = 0;
                int maxThreads = OptionCache.GetOptionValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.Srodowiska.MaxThreads).AsInt(1);
                minCount = max / maxThreads;
                int rest = max % maxThreads;
                if (rest > 0)
                    minCount++;
                List<Thread> threads = new List<Thread>();
                List<string> names = new List<string>();
                
                foreach (DataRow r in envsRows)
                {
                    if (!r.CanRead())
                        continue;
                    names.Add(r["STP_SR_NAZWA"].AsString());
                    if (names.Count >= minCount)
                    {
                        Thread t = new Thread(new ParameterizedThreadStart(UpdateDbTh));
                        a.ThreadsCount++;
                        t.Start(new UpdateDbInfo(names.ToArray(), a));

                        names = new List<string>();
                    }
                }
                if (names.Count >= minCount)
                {
                    Thread t = new Thread(new ParameterizedThreadStart(UpdateDbTh));
                    t.Start(new UpdateDbInfo(names.ToArray(), a));
                }
                try
                {
                    while (a.ThreadsCount > 0)
                    {
                        Thread.Sleep(50);
                    }
                }
                finally
                {
                    try
                    {
                        if (a.Row != null)
                        {
                            try
                            {
                                if (FormMain.Instance.InvokeRequired)
                                {
                                    FormMain.Instance.Invoke(new Action(() =>
                                    {
                                        a.Row["STATUS"] = BuildHelper.Scheduler.Zadanie.Statusy.Zakonczone;
                                    }));
                                }
                                else
                                {
                                    a.Row["STATUS"] = BuildHelper.Scheduler.Zadanie.Statusy.Zakonczone;
                                }
                            }
                            catch (Exception ex) { ex.Log(); }
                        }
                        BrowserCache.RefreshCacheForTable("STP_BAZY_DANYCH");
                        FormMain.CloseAlertById(GetUpdateAllDbId(a.Index));
                    }
                    catch { }
                }
            }
        }
        #endregion

        public class DbData
        {
            public DbData(string envName)
            {
                EnvName = envName;
            }
            public DbData()
            {

            }
            public string EnvName
            {
                get;
                set;
            }
            public string UserName
            {
                get;
                set;
            }
            public string Pass
            {
                get;
                set;
            }
            public string Sid
            {
                get;
                set;
            }
            public string Service
            {
                get;
                set;
            }
            public int Port
            {
                get;
                set;
            }
            public string Host
            {
                get;
                set;
            }
            public string Wersja
            {
                get;
                set;
            }
        }
        public static void OpenDB(DataRow r)
        {
            if (r != null)
            {
                string host = r["STP_BD_HOST"].AsString().Trim();
                string sid = r["STP_BD_SID"].AsString().Trim();
                string service = r["STP_BD_SERVICE"].AsString().Trim();
                string port = r["STP_BD_PORT"].AsString().Trim();
                string user = r["STP_BD_USER"].AsString().Trim();
                string pass = r["STP_BD_PASS"].AsString().Trim();
                string env = r["STP_BD_NAZWA"].AsString().Trim();

                if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.UzywajServiceDlaPlsql))
                {
                    if (service.IsNull())
                        service = sid;
                }

                string connection = user + "/" + pass;
                string name = "";
                string nazwa = "";

                if (GlobalTools.DBTools.AddTnsNames(env, host, port, service, sid))
                    name = GlobalTools.DBTools.GetCorrectEnvName(env);
                
                if (name.IsNotNull())
                    nazwa = "@" + name;
                else
                    nazwa += "@" + host + ":" + port + (service.IsNotNull() ? ("/" + service) : (":" + sid));

                connection += nazwa;

                if (GlobalTools.DBTools.CanUsePlSqlDeveloper())
                {
                    string mask = user + nazwa;

                    Process old = GlobalTools.ProcessTools.GetRunningProcessByWindowText("plsqldev", mask.XEscape());
                    bool run = true;
                    if (old != null)
                    {
                        DialogResult dlg = FormMain.Instance.ShowDxYNCQuestionDialog("PL/SQL Developer dla połączenia " + mask+ " jest już otwarty.", DxFormExt.GetYesNoCancelDialogResultText("Przełącz na", "Otwórz", "Anuluj"));
                        if (dlg == DialogResult.Yes)
                        {
                            old.BringWindowToFront();
                            run = false;
                        }
                        else if (dlg == DialogResult.Cancel)
                        {
                            run = false;
                        }
                    }
                    if (run)
                    {
                        string args = "nosplash userid=" + connection;
                        Process p = Process.Start(new ProcessStartInfo(OptionCache.GetOptionStringValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.PlSqlDeveloper), args));

                        if (OptionCache.GetOptionBoolValue(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.OpenSqlWindow))
                        {
                            ExtThread t = new ExtThread();
                            t.Start(p);
                        }
                    }
                }
                //else if (GlobalTools.DBTools.CanUseSqlTools())
                //{
                //    string args = "/c=" + connection;
                //    Process p = Process.Start(new ProcessStartInfo(OptionCache.GetOptionStringValue(Init.InitFormOptionNames.Setup_Group.Rozne_Group.BazyDanych.SqlTools), args));
                //}
                else
                {
                    FormMain.Instance.ShowDxInfoDialog("PL/SQL Developer nie został odnaleziony. Sprawdź opcje.\n" +
                        GlobalTools.GetOptionPath(Init.InitFormOptionNames.Setup_Group.Definicje_Group.BazyDanych.PlSqlDeveloper));
                }
            }
        }
        private class ExtThread
        {
            Thread _Thread;
            Process _Process;
            public ExtThread()
            {
                _Thread = new Thread(new ThreadStart(run));
                _Thread.IsBackground = true;
            }

            private void run()
            {
                Process p;
                while (true)
                {
                    if (Program.IsExit)
                        return;

                    Application.DoEvents();
                    Thread.Sleep(10);
                    try
                    {
                        p = User32.GetActiveWindowProcess();
                        if (p != null && p.Id == _Process.Id)
                        {
                            System.Threading.Thread.Sleep(1000);
                            p = User32.GetActiveWindowProcess();
                            if (p != null && p.Id == _Process.Id)
                            {
                                InputSimulator.SimulateKeyPress(VirtualKeyCode.MENU);
                                InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_F);
                                InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_N);
                                InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_S);
                                return;
                            }
                        }
                    }
                    catch { }
                }
            }

            public void Start(Process p)
            {
                _Process = p;
                if (p != null)
                {
                    _Thread.Start();
                }
            }
        }
    }
}
